home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / 7edit / source / svaecompare.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  7.9 KB  |  324 lines

  1. /*
  2.     File:        SVAECompare.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by: Original version by Jon Lansdell and Nigel Humphreys.
  7.                 3.1 updates by Greg Sutton.
  8.  
  9.     Copyright:    Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/20/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24. #include "SVAECompare.h"
  25.  
  26. #include <AEPackObject.h>
  27. #include "SVEditGlobals.h"
  28. #include "SVEditUtils.h"
  29. #include "SVEditAEUtils.h"
  30. #include "SVEditWindow.h"
  31. #include "SVEditFile.h"
  32. #include "SVAppleEvents.h"
  33.  
  34. #include "SVToken.h"
  35. #include "SVAECountElements.h"
  36. #include "SVAEGetData.h"
  37.  
  38. #include <string.h>
  39.  
  40.  
  41. #pragma segment AppleEvent
  42.  
  43.  
  44. OSErr    InstallObjectCallbacks(void)
  45. {
  46.     OSErr    err;
  47.  
  48.     err = AESetObjectCallbacks(NewOSLCompareProc(MyCompareProc),
  49.                                 NewOSLCountProc(MyCountProc),
  50.                                 NULL, NULL, NULL, NULL, NULL);
  51.                                 
  52.     return(err);
  53. }
  54.  
  55.  
  56. pascal OSErr    MyCompareProc(DescType oper, const AEDesc* obj1, const AEDesc* obj2, Boolean* result)
  57. {
  58.     AEDesc        desc1     = {typeNull, NULL};
  59.     AEDesc        desc2     = {typeNull, NULL};
  60.     AEDesc        tempDesc = {typeNull, NULL};
  61.     OSErr        err;
  62.     
  63.     err = ExtractData(obj1, &desc1);
  64.     if (err != noErr) goto done;
  65.     err = ExtractData(obj2, &desc2);
  66.     if (err != noErr) goto done;
  67.  
  68.     // Make sure the 2 data types are the same
  69.     if (desc1.descriptorType != desc2.descriptorType)
  70.     {
  71.         err = AEDuplicateDesc(&desc2, &tempDesc);
  72.         if (err != noErr) goto done;
  73.         err = AEDisposeDesc(&desc2);
  74.         err = AECoerceDesc(&tempDesc, desc1.descriptorType, &desc2);
  75.         if (err != noErr)                        // If we can't coerce one way, try
  76.         {                                        // the opposite way.
  77.             err = AEDuplicateDesc(&tempDesc, &desc2);    // We disposed of desc2
  78.             err = AEDisposeDesc(&tempDesc);
  79.             err = AEDuplicateDesc(&desc1, &tempDesc);
  80.             if (err != noErr) goto done;
  81.             err = AEDisposeDesc(&desc1);
  82.             err = AECoerceDesc(&tempDesc, desc2.descriptorType, &desc1);
  83.             if (err != noErr) goto done;
  84.         }
  85.     }
  86.     
  87.     // Now that we know that the 2 types are the same, go ahead and run the compare
  88.     switch(desc1.descriptorType)
  89.     {
  90.         case typeChar:
  91.             err = MyCompareText(oper, &desc1, &desc2, result);
  92.             break;
  93.         
  94.         case typeShortInteger:
  95.         case typeLongInteger:
  96.             err = MyCompareInteger(oper, &desc1, &desc2, result);
  97.             break;
  98.  
  99.         case typeBoolean:
  100.             err = MyCompareBoolean(oper, &desc1, &desc2, result);
  101.             break;
  102.                 
  103.         default:
  104.             err = errAEWrongDataType;
  105.     }
  106.     
  107. done:
  108.     if (desc1.dataHandle)
  109.         (void) AEDisposeDesc(&desc1);
  110.     if (desc2.dataHandle)
  111.         (void) AEDisposeDesc(&desc2);
  112.     if (tempDesc.dataHandle)
  113.         (void) AEDisposeDesc(&tempDesc);
  114.     
  115.     return(err);
  116. }
  117.  
  118.  
  119. OSErr    ExtractData(const AEDesc *sourceDesc, AEDesc *theData)
  120. {
  121.     AEDesc        intermediateDesc = {typeNull, NULL};
  122.     OSErr        err;
  123.     
  124.     // This routine can receive: An Object specifier, an object token, a property token, or
  125.     // some data (TEXT, Rectangle, etc.). It needs to convert whatever it's handed into data
  126.     // and return that.
  127.     
  128.     // If we don't have any data, complain
  129.     if (sourceDesc->descriptorType == typeNull || sourceDesc->dataHandle == NULL)
  130.         return(errAENoSuchObject);
  131.     
  132.     // If it's an object specifier, resolve into a token
  133.     if (sourceDesc->descriptorType == typeObjectSpecifier)
  134.         err = AEResolve(sourceDesc, kAEIDoMinimum, &intermediateDesc);
  135.     else    // Otherwise, just copy it
  136.         err = AEDuplicateDesc(sourceDesc, &intermediateDesc);
  137.  
  138.     if (err != noErr) goto done;
  139.     
  140.     // Now that we have a token, read from it
  141.     switch (intermediateDesc.descriptorType)
  142.     {
  143.         case typeMyApplProp:
  144.         case typeMyTextProp:
  145.         case typeMyWindowProp:
  146.         case typeMyText:
  147.             err = HandleGetData(&intermediateDesc, theData);
  148.             break;
  149.  
  150.         default:
  151.             // This is probably raw data , so pass it back up the line
  152.             err = AEDuplicateDesc(&intermediateDesc, theData);
  153.     }
  154.  
  155. done:
  156.     if (intermediateDesc.dataHandle)
  157.         (void) AEDisposeDesc(&intermediateDesc);
  158.  
  159.     return(err);
  160. }
  161.  
  162.  
  163. OSErr    MyCompareText(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  164. {
  165.     int        compareResult;
  166.     long    compareSize;
  167.     long    textSize1, textSize2;
  168.     char    *testStr, *compareStr;
  169.     OSErr    err = noErr;
  170.     
  171.     textSize1 = GetHandleSize(desc1->dataHandle);
  172.     HLockHi(desc1->dataHandle);
  173.     textSize2 = GetHandleSize(desc2->dataHandle);
  174.     HLockHi(desc2->dataHandle);
  175.     if (textSize1 <= textSize2)
  176.     {
  177.         switch (oper)
  178.         {
  179.             case kAEBeginsWith:        // Can't begin or end or contain any string
  180.             case kAEEndsWith:        // longer than itself
  181.             case kAEContains:
  182.                 *result = false;
  183.                 return(noErr);
  184.         }
  185.     
  186.         compareSize = textSize1;
  187.     }
  188.     else
  189.         compareSize = textSize2;
  190.     
  191.     switch (oper)
  192.     {
  193.         case kAEEndsWith:            // Offset to end of string
  194.             testStr = (char *)(*desc1->dataHandle + textSize1 - textSize2);    
  195.             break;
  196.         
  197.         case kAEContains:
  198.             testStr = NewPtr(textSize1 + 1);
  199.             BlockMove(*desc1->dataHandle, testStr, textSize1);
  200.             testStr[textSize1] = '\0';
  201.             compareStr = NewPtr(textSize2 + 1);
  202.             BlockMove(*desc2->dataHandle, compareStr, textSize2);
  203.             compareStr[textSize2] = '\0';
  204.             *result = (NULL != strstr(testStr,compareStr));
  205.             DisposePtr(testStr);
  206.             DisposePtr(compareStr);
  207.             return(noErr);
  208.         
  209.         default:
  210.             testStr = (char *)*desc1->dataHandle;
  211.     }
  212.     
  213.     compareResult = strncmp(testStr, (char *)*desc2->dataHandle, compareSize);
  214.     
  215.     HUnlock(desc1->dataHandle);
  216.     HUnlock(desc2->dataHandle);
  217.  
  218.     switch (oper)
  219.     {
  220.         case kAEEquals:
  221.             *result = (textSize1 == textSize2 && compareResult == 0);
  222.             break;
  223.  
  224.         case kAEBeginsWith:
  225.         case kAEEndsWith:
  226.             *result = (compareResult == 0);
  227.             break;
  228.  
  229.         case kAELessThan:
  230.             *result = (compareResult < 0);
  231.             break;
  232.         
  233.         case kAELessThanEquals:
  234.             *result = (compareResult <= 0);
  235.             break;
  236.         
  237.         case kAEGreaterThan:
  238.             *result = (compareResult > 0);
  239.             break;
  240.         
  241.         case kAEGreaterThanEquals:
  242.             *result = (compareResult >= 0);
  243.             break;
  244.         
  245.         default:
  246.             err = errAEBadTestKey;
  247.     }
  248.  
  249.     return(err);
  250. }
  251.  
  252.  
  253. OSErr    MyCompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  254. {
  255.     long    num1, num2;
  256.     AEDesc    longDesc = {typeNull, NULL};
  257.     OSErr    err;
  258.     
  259.     // Make each number is a long integer (in case it's a short integer) before extracting the data
  260.     err = AECoerceDesc(desc1, typeLongInteger, &longDesc);
  261.     if (err != noErr) goto done;
  262.     num1 = **(long **)longDesc.dataHandle;
  263.     (void) AEDisposeDesc(&longDesc);    // We're done with longDesc, so dispose of it
  264.     longDesc.dataHandle = NULL;            // Mark this as disposed
  265.     
  266.     err = AECoerceDesc(desc2, typeLongInteger, &longDesc);
  267.     if (err != noErr) goto done;
  268.     num2 = **(long **)longDesc.dataHandle;
  269.     // No need to dispose of this descriptor, as the code at "done" will do it for us
  270.     
  271.     switch (oper)
  272.     {
  273.         case kAEEquals:
  274.             *result = (num1 == num2);
  275.             break;
  276.         
  277.         case kAELessThan:
  278.             *result = (num1 < num2);
  279.             break;
  280.         
  281.         case kAELessThanEquals:
  282.             *result = (num1 <= num2);
  283.             break;
  284.         
  285.         case kAEGreaterThan:
  286.             *result = (num1 > num2);
  287.             break;
  288.         
  289.         case kAEGreaterThanEquals:
  290.             *result = (num1 >= num2);
  291.             break;
  292.         
  293.         default:
  294.             err = errAEBadTestKey;
  295.     }
  296.     
  297. done:
  298.     if (longDesc.dataHandle)
  299.         (void) AEDisposeDesc(&longDesc);
  300.  
  301.     return err;
  302. } // MyCompareInteger
  303.  
  304.  
  305. OSErr    MyCompareBoolean (DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
  306. {
  307.     Boolean    bool1, bool2;
  308.     OSErr    err = noErr;
  309.     
  310.     // Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE
  311.     // We'll use a test to convert this into C's boolean notation, just to make this easier to
  312.     // debug
  313.     
  314.     bool1 = (**(char **)desc1->dataHandle) != 0;
  315.     bool2 = (**(char **)desc2->dataHandle) != 0;
  316.     
  317.     if (oper == kAEEquals) 
  318.         *result = (bool1 == bool2);
  319.     else
  320.         err = errAEBadTestKey;        // No other tests make sense
  321.  
  322.     return err;
  323. } // MyCompareBoolean
  324.